/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zlang_in.h"

static int SyntaxAnalysisScan_func_out_param( struct ZlangRuntime *rt , char *obj_name , struct ZlangFunction *func )
{
	struct ZlangTokenDataUnitHeader		*parent_obj_name_info = NULL ;
	char					*parent_obj_name = NULL ;
	struct ZlangFunctionParameter		*param = NULL ;
	
	PEEKTOKEN( rt , parent_obj_name_info , parent_obj_name )
	QueryCharsetAliasAndChangeTokenInfo( rt , parent_obj_name_info , & parent_obj_name );
	if( obj_name && parent_obj_name_info->token_type == TOKEN_TYPE_IDENTIFICATION && STRCMP( parent_obj_name , == , obj_name ) )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SyntaxAnalysisScan_func_out_param : peek[%s]" , parent_obj_name )
	}
	else if( obj_name && parent_obj_name_info->token_type == TOKEN_TYPE_BIT_REVERSE )
	{
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SyntaxAnalysisScan_func_out_param : peek[%s]" , parent_obj_name )
	}
	else
	{
		NEXTTOKEN( rt )
		
		param = SetFunctionOutputParameterInFunction( rt , func , parent_obj_name ) ;
		if( param == NULL )
			return GET_RUNTIME_ERROR_NO(rt);
		
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SyntaxAnalysisScan_func_out_param : add out param , parent_obj_name[%s] obj_name[%s]" , param->parent_obj_name , param->obj_name )
	}
	
	return 0;
}

static int SyntaxAnalysisScan_func_in_params( struct ZlangRuntime *rt , struct ZlangFunction *func )
{
	struct ZlangTokenDataUnitHeader		*token_info = NULL ;
	char					*token = NULL ;
	struct ZlangTokenDataUnitHeader		*parent_obj_name_info = NULL ;
	char					*parent_obj_name = NULL ;
	struct ZlangTokenDataUnitHeader		*obj_name_info = NULL ;
	char					*obj_name = NULL ;
	struct ZlangFunctionParameter		*param = NULL ;
	
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_BEGIN_OF_SUB_EXPRESSION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect '('" )
		return ZLANG_ERROR_SYNTAX;
	}
	
	for( ; ; )
	{
		TRAVELTOKEN_AND_SAVEINFO( rt , parent_obj_name_info , parent_obj_name )
		QueryCharsetAliasAndChangeTokenInfo( rt , parent_obj_name_info , & parent_obj_name );
		if( parent_obj_name_info->token_type == TOKEN_TYPE_END_OF_SUB_EXPRESSION )
		{
			break;
		}
		else if( parent_obj_name_info->token_type == TOKEN_TYPE_IDENTIFICATION )
		{
			TRAVELTOKEN_AND_SAVEINFO( rt , obj_name_info , obj_name )
			if( obj_name_info->token_type == TOKEN_TYPE_IDENTIFICATION )
			{
				param = AddFunctionInputParameterInFunction( rt , func , parent_obj_name , obj_name ) ;
				if( param == NULL )
					return ZLANG_ERROR_ALLOC;
				
				TEST_RUNTIME_DEBUG( rt )
				{
					PRINT_TABS_AND_FORMAT( rt , "SyntaxAnalysisScan_func_in_params : add in param to list , parent_obj_name[%s] obj_name[%s]" , param->parent_obj_name , param->obj_name );
				}
			}
			else
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect IDENTIFICATION but '%s'" , obj_name )
				return ZLANG_ERROR_SYNTAX;
			}
		}
		else if( parent_obj_name_info->token_type == TOKEN_TYPE_ETC )
		{
			param = AddFunctionInputParameterInFunction( rt , func , "..." , NULL ) ;
			if( param == NULL )
				return ZLANG_ERROR_ALLOC;
			
			TEST_RUNTIME_DEBUG( rt )
			{
				PRINT_TABS_AND_FORMAT( rt , "SyntaxAnalysisScan_func_in_params : add in param to list , parent_obj_name[%s] obj_name[%s]" , param->parent_obj_name , param->obj_name );
			}
		}
		else
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect ')' or IDENTIFICATION but '%s'" , parent_obj_name )
			return ZLANG_ERROR_SYNTAX;
		}
		
		PEEKTOKEN( rt , token_info , token )
		if( token_info->token_type == TOKEN_TYPE_PART_OF_STATEMENT )
		{
			NEXTTOKEN( rt )
		}
		else if( token_info->token_type == TOKEN_TYPE_END_OF_SUB_EXPRESSION )
		{
			;
		}
		else
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect ',' or ')' but '%s'" , token )
			return ZLANG_ERROR_SYNTAX;
		}
	}
	
	return 0;
}

struct ZlangJumpTokenInfo
{
	struct ZlangTokenDataUnitHeader		*switch_or_case_token_info ;
	
	struct ZlangTokenDataUnitHeader		*try_token_info ;
	struct ZlangTokenDataUnitHeader		*catch_token_info ;
} ;

static int SyntaxAnalysisScan_func_body( struct ZlangRuntime *rt , struct ZlangTokenDataUnitHeader *begin_of_statement_segment_token_info , struct ZlangJumpTokenInfo *previous_jump_token_info , struct ZlangTokenDataUnitHeader **token_info , char **token , uint32_t statment_segment_depth , enum TokenType end_of_statement_segment )
{
	struct ZlangTokenDataPageHeader		*current_token_datapage_header = NULL ;
	char					*current_token_dataunit = NULL ;
	
	struct ZlangJumpTokenInfo		jump_token_info ;
	struct ZlangTokenDataUnitHeader		*new_begin_of_statement_segment_token_info = NULL ;
	
	int					nret = 0 ;
	
	memset( & jump_token_info , 0x00 , sizeof(struct ZlangJumpTokenInfo) );
	for( ; ; )
	{
		current_token_datapage_header = rt->travel_token_datapage_header ;
		current_token_dataunit = rt->travel_token_dataunit ;
		
		TRAVELTOKEN( rt , (*token_info) , (*token) )
		if( (*token_info)->token_type == TOKEN_TYPE_SWITCH )
		{
			jump_token_info.switch_or_case_token_info = (*token_info) ;
		}
		else if( (*token_info)->token_type == TOKEN_TYPE_CASE || (*token_info)->token_type == TOKEN_TYPE_DEFAULT )
		{
			if( previous_jump_token_info->switch_or_case_token_info )
			{
				previous_jump_token_info->switch_or_case_token_info->p1 = current_token_datapage_header ;
				previous_jump_token_info->switch_or_case_token_info->p2 = current_token_dataunit ;
				
				previous_jump_token_info->switch_or_case_token_info = (*token_info) ;
			}
		}
		else if( (*token_info)->token_type == TOKEN_TYPE_TRY )
		{
			jump_token_info.try_token_info = jump_token_info.catch_token_info = (*token_info) ;
		}
		else if( (*token_info)->token_type == TOKEN_TYPE_CATCH )
		{
			if( previous_jump_token_info->catch_token_info )
			{
				previous_jump_token_info->catch_token_info->p1 = current_token_datapage_header ;
				previous_jump_token_info->catch_token_info->p2 = current_token_dataunit ;
				
				previous_jump_token_info->catch_token_info = (*token_info) ;
			}
		}
		else if( (*token_info)->token_type == TOKEN_TYPE_FINALLY )
		{
			if( previous_jump_token_info->try_token_info )
			{
				previous_jump_token_info->try_token_info->p7 = current_token_datapage_header ;
				previous_jump_token_info->try_token_info->p8 = current_token_dataunit ;
			}
		}
		else if( (*token_info)->token_type == TOKEN_TYPE_BEGIN_OF_STATEMENT_SEGMENT )
		{
			new_begin_of_statement_segment_token_info = (*token_info) ;
			
			nret = SyntaxAnalysisScan_func_body( rt , new_begin_of_statement_segment_token_info , & jump_token_info , token_info , token , statment_segment_depth+1 , TOKEN_TYPE_END_OF_STATEMENT_SEGMENT ) ;
			if( nret )
				return nret;
			memset( & jump_token_info , 0x00 , sizeof(struct ZlangJumpTokenInfo) );
		}
		else if( (*token_info)->token_type == end_of_statement_segment )
		{
			begin_of_statement_segment_token_info->p1 = current_token_datapage_header ;
			begin_of_statement_segment_token_info->p2 = current_token_dataunit ;
			
			break;
		}
	}
	
	return 0;
}

int SyntaxAnalysisScan_func( struct ZlangRuntime *rt , char *obj_name , struct ZlangFunction **pp_func )
{
	struct ZlangTokenDataUnitHeader		*token_info = NULL ;
	char					*token = NULL ;
	struct ZlangFunction			*func = NULL ;
	struct ZlangTokenDataUnitHeader		*begin_of_statment_segment_token_info = NULL ;
	struct ZlangTokenDataUnitHeader		*func_name_info = NULL ;
	char					*func_name = NULL ;
	char					*destractor = NULL ;
	char					*full_func_name = NULL ;
	
	int					nret = 0 ;
	
	func = CreateFunction( rt , NULL , NULL , NULL ) ;
	if( func == NULL )
		return GET_RUNTIME_ERROR_NO(rt);
	
	/*
		[sync] "function" out_param func_name '(' in_params ')' '{' ... '}'
                       #1         #2        #3        #4  #5        #6  #7  #8  #9
		
		out_params = parent_obj_name
		
		in_params = parent_obj_name obj_name
		in_params = parent_obj_name & obj_name
		in_params = '('parent_obj_name obj_name,in_params')'
		
		parent_obj_name = object_name
		parent_obj_name = <agent_obj_name> obj_name
	*/
	
	/* #2 */
	nret = SyntaxAnalysisScan_func_out_param( rt , obj_name , func ) ;
	if( nret )
	{
		FreeFunction( func );
		return nret;
	}
	
	/* #3 */
	if( GetFunctionOutParameter(func) )
	{
		TRAVELTOKEN( rt , func_name_info , func_name )
		nret = SetFunctionName( rt , func , func_name ) ;
		if( nret )
		{
			FreeFunction( func );
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	else
	{
		if( obj_name == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "declare constractor or destractor error" )
			FreeFunction( func );
			return GET_RUNTIME_ERROR_NO(rt);
		}
		
		TRAVELTOKEN( rt , func_name_info , func_name )
		if( func_name_info->token_type == TOKEN_TYPE_BIT_REVERSE )
		{
			destractor = func_name ;
			
			TRAVELTOKEN( rt , func_name_info , func_name )
			if( STRCMP( func_name , != , obj_name ) )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "declare destractor name must be as object name" )
				FreeFunction( func );
				return GET_RUNTIME_ERROR_NO(rt);
			}
			
			nret = SetFunctionName2( rt , func , destractor , func_name ) ;
			if( nret )
			{
				FreeFunction( func );
				return GET_RUNTIME_ERROR_NO(rt);
			}
		}
		else
		{
			nret = SetFunctionName( rt , func , func_name ) ;
			if( nret )
			{
				FreeFunction( func );
				return GET_RUNTIME_ERROR_NO(rt);
			}
		}
	}
	
	/* #4,#5,#6 */
	nret = SyntaxAnalysisScan_func_in_params( rt , func ) ;
	if( nret )
	{
		FreeFunction( func );
		return nret;
	}
	
	/* #7 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type == TOKEN_TYPE_BEGIN_OF_STATEMENT_SEGMENT )
	{
		begin_of_statment_segment_token_info = token_info ;
		
		func->func_begin_token_datapage_header = rt->travel_token_datapage_header ;
		func->func_begin_token_dataunit = rt->travel_token_dataunit ;
		
		/* #8,#9 */
		nret = SyntaxAnalysisScan_func_body( rt , begin_of_statment_segment_token_info , NULL , & token_info , & token , 1 , TOKEN_TYPE_END_OF_STATEMENT_SEGMENT ) ;
		if( nret )
		{
			FreeFunction( func );
			return nret;
		}
		
		func->func_end_over_token_datapage_header = rt->travel_token_datapage_header ;
		func->func_end_over_token_dataunit = rt->travel_token_dataunit ;
	}
	else if( token_info->token_type == TOKEN_TYPE_END_OF_STATEMENT )
	{
		;
	}
	else
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect '{' or ';'" )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	full_func_name = GenerateFullFunctionName( rt , func , & (func->in_params) , func->out_param ) ;
	if( full_func_name == NULL )
	{
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	LinkFullFunctionName( func , full_func_name );
	
	TEST_RUNTIME_DEBUG( rt )
	{
		PRINT_TABS_AND_FORMAT( rt , "SyntaxAnalysisScan_func : add func func_name[%s] full_func_name[%s]" , func->func_name , func->full_func_name );
	}
	
	if( pp_func )
		(*pp_func) = func ;
	return 0;
}

int SyntaxAnalysisScan_object_intercept( struct ZlangRuntime *rt , struct ZlangIntercept **pp_intercept )
{
	struct ZlangFunction		*func = NULL ;
	unsigned char			opportunity ;
	struct ZlangTokenDataUnitHeader	*token_info = NULL ;
	char				*token = NULL ;
	struct ZlangTokenDataUnitHeader	*prop_name_info = NULL ;
	char				*prop_name = NULL ;
	struct ZlangTokenDataUnitHeader	*param_name_info = NULL ;
	char				*param_name = NULL ;
	struct ZlangFunctionParameter	*func_in_param = NULL ;
	struct ZlangTokenDataUnitHeader	*begin_of_statment_segment_token_info = NULL ;
	char				*full_func_name = NULL ;
	struct ZlangIntercept		*intercept = NULL ;
	int				nret = 0 ;
	
	func = CreateFunction( rt , NULL , NULL , NULL ) ;
	if( func == NULL )
		return GET_RUNTIME_ERROR_NO(rt);
	
	/* #34 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type == TOKEN_TYPE_SET )
	{
		opportunity = ZLANG_INTERCEPT_SET ;
	}
	else if( token_info->token_type == TOKEN_TYPE_GET )
	{
		opportunity = ZLANG_INTERCEPT_GET ;
	}
	else
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect 'set' or 'get' after 'intercept' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #37 */
	TRAVELTOKEN( rt , prop_name_info , prop_name )
	if( prop_name_info->token_type != TOKEN_TYPE_IDENTIFICATION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect 'prop' after intercept opportunity , but '%s'" , prop_name )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	nret = SetFunctionName( rt , func , prop_name ) ;
	if( nret )
	{
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #38 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_BEGIN_OF_SUB_EXPRESSION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect '(' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #39 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_OBJECT )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect 'object' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #40 */
	TRAVELTOKEN( rt , param_name_info , param_name )
	if( param_name_info->token_type != TOKEN_TYPE_IDENTIFICATION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect TOKEN_TYPE_IDENTIFICATION , but '%s'" , param_name )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	func_in_param = AddFunctionInputParameterInFunction( rt , func , ZLANG_OBJECT_object , param_name ) ;
	if( func_in_param == NULL )
	{
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #41 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_END_OF_SUB_EXPRESSION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect ')' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #42 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_BEGIN_OF_STATEMENT_SEGMENT )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect '{' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	begin_of_statment_segment_token_info = token_info ;
	
	func->func_begin_token_datapage_header = rt->travel_token_datapage_header ;
	func->func_begin_token_dataunit = rt->travel_token_dataunit ;
	
	nret = SyntaxAnalysisScan_func_body( rt , begin_of_statment_segment_token_info , NULL , & token_info , & token , 1 , TOKEN_TYPE_END_OF_STATEMENT_SEGMENT ) ;
	if( nret )
	{
		FreeFunction( func );
		return nret;
	}
	
	func->func_end_over_token_datapage_header = rt->travel_token_datapage_header ;
	func->func_end_over_token_dataunit = rt->travel_token_dataunit ;
	
	full_func_name = GenerateFullFunctionName( rt , func , & (func->in_params) , func->out_param ) ;
	if( full_func_name == NULL )
	{
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	LinkFullFunctionName( func , full_func_name );
	
	/* create intercept */
	intercept = CreateIntercept( rt , opportunity , prop_name , func ) ;
	if( intercept == NULL )
	{
		FreeFunction( func );
		return nret;
	}
	
	if( pp_intercept )
		(*pp_intercept) = intercept ;
	return 0;
}

int SyntaxAnalysisScan_object( struct ZlangRuntime *rt , struct ZlangObject **pp_obj )
{
	struct ZlangTokenDataUnitHeader			*token_info = NULL ;
	char						*token = NULL ;
	struct ZlangTokenDataUnitHeader			*inherit_info = NULL ;
	char						*inherit = NULL ;
	struct ZlangObject				*obj = NULL ;
	struct ZlangTokenDataUnitHeader			*obj_name_info = NULL ;
	char						*obj_name = NULL ;
	struct ZlangTokenDataUnitHeader			*inherit_name_info = NULL ;
	char						*inherit_name = NULL ;
	struct ZlangObject				*inherit_obj = NULL ;
	struct ZlangTokenDataUnitHeader			*interf_name_info = NULL ;
	char						*interf_name = NULL ;
	struct ZlangInterface				*interf = NULL ;
	struct ZlangObject				*parent_obj = NULL ;
	struct ZlangFunction				*func = NULL ;
	struct ZlangInterpretStatementSegmentContext	interp_stat_seg_ctx ;
	struct ZlangInterpretStatementContext		interp_stat_ctx ;
	struct ZlangInterpretExpressionContext		interp_expr_ctx ;
	struct ZlangIntercept				*intercept = NULL ;
	struct ZlangObject				*prop = NULL ;
	
	int						nret = 0 ;
	
	/*
		'object' obj_name [ 'extends' inherit_object_name ] [ 'implements' interf_name ]
		#1       #2       #3        #4
		{
		#9
			['public|private'] ['atomic'] parent_obj_name '<' ext_obj_name , ext_obj2_name '>'  obj_name ;
                        #13              #14                                                   #15
			
			['public|private'] ['sync'] function ...
			#23              #24
			
			'intercept' 'set'|'get' member '(' 'object' o ')' '{' ...
			#33         #34         #37        #39        #41
			                               #38          #40   #42
		}
		#99
	*/
	
	/* #2 */
	TRAVELTOKEN_AND_SAVEINFO( rt , obj_name_info , obj_name )
	
	nret = CloneObject( rt , & obj , obj_name , NULL ) ;
	if( nret )
		return GET_RUNTIME_ERROR_NO(rt);
	
	/* #3 */
	TRAVELTOKEN_AND_SAVEINFO( rt , inherit_info , inherit )
	if( inherit_info->token_type == TOKEN_TYPE_EXTENDS )
	{
		TRAVELTOKEN_AND_SAVEINFO( rt , inherit_name_info , inherit_name )
		if( inherit_name_info->token_type != TOKEN_TYPE_IDENTIFICATION )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect IDENTIFICATION or '{' but '%s'" , inherit_name )
			return ZLANG_ERROR_SYNTAX;
		}
		
		inherit_obj = QueryGlobalObjectByObjectName( rt , inherit_name ) ;
		if( inherit_obj == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DEFINED , "object '%s' not imported or defined" , inherit_name )
			return GET_RUNTIME_ERROR_NO(rt);
		}
		
		SetObjectAncestorFunctionsEntity( rt , obj , GetObjectFunctionsEntity(inherit_obj) );
		
		nret = CopyObjectProperties( rt , obj , inherit_obj ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CopyObjectProperties failed[%d]" , nret )
			return nret;
		}
		
		TRAVELTOKEN_AND_SAVEINFO( rt , token_info , token )
		if( token_info->token_type != TOKEN_TYPE_BEGIN_OF_STATEMENT_SEGMENT )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect ',' or '{' but '%s'" , token )
			return ZLANG_ERROR_SYNTAX;
		}
	}
	else if( inherit_info->token_type == TOKEN_TYPE_IMPLEMENTS )
	{
		TRAVELTOKEN_AND_SAVEINFO( rt , interf_name_info , interf_name )
		if( interf_name_info->token_type != TOKEN_TYPE_IDENTIFICATION )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect IDENTIFICATION or '{' but '%s'" , interf_name )
			return ZLANG_ERROR_SYNTAX;
		}
		
		interf = QueryGlobalInterfaceByInterfaceName( rt , interf_name ) ;
		if( interf == NULL )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_OBJECT_NOT_IMPORTED_OR_DEFINED , "interf '%s' not imported or defined" , interf_name )
			return GET_RUNTIME_ERROR_NO(rt);
		}
		
		SetObjectAncestorFunctionsEntity( rt , obj , GetObjectFunctionsEntity(GetInterfaceInner(interf)) );
		
		nret = CopyObjectProperties( rt , obj , GetInterfaceInner(interf) ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CopyObjectProperties failed[%d]" , nret )
			return nret;
		}
		
		TRAVELTOKEN_AND_SAVEINFO( rt , token_info , token )
		if( token_info->token_type != TOKEN_TYPE_BEGIN_OF_STATEMENT_SEGMENT )
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect ',' or '{' but '%s'" , token )
			return ZLANG_ERROR_SYNTAX;
		}
	}
	else if( inherit_info->token_type == TOKEN_TYPE_BEGIN_OF_STATEMENT_SEGMENT )
	{
		SetObjectAncestorFunctionsEntity( rt , obj , GetObjectFunctionsEntity(GetZObjectInRuntimeObjectsHeap(rt)) );
		
		nret = CopyObjectProperties( rt , obj , GetZObjectInRuntimeObjectsHeap(rt) ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CopyObjectProperties failed[%d]" , nret )
			return nret;
		}
	}
	else
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect 'extends' or 'implements' or '{'" )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	memset( & interp_stat_seg_ctx , 0x00 , sizeof(struct ZlangInterpretStatementSegmentContext) );
	memset( & interp_stat_ctx , 0x00 , sizeof(struct ZlangInterpretStatementContext) );
	memset( & interp_expr_ctx , 0x00 , sizeof(struct ZlangInterpretExpressionContext) );
	for( ; ; )
	{
		/* #13 or #23 or #99 */
		TRAVELTOKEN_AND_SAVEINFO( rt , token_info , token )
		QueryCharsetAliasAndChangeTokenInfo( rt , token_info , & token );
		if( token_info->token_type == TOKEN_TYPE_PUBLIC )
		{
			interp_stat_ctx.has_access_qualifier = ZLANG_ACCESSQUALIFIER_PUBLIC ;
		}
		else if( token_info->token_type == TOKEN_TYPE_PRIVATE )
		{
			interp_stat_ctx.has_access_qualifier = ZLANG_ACCESSQUALIFIER_PRIVATE ;
		}
		else if( token_info->token_type == TOKEN_TYPE_CONST )
		{
			interp_stat_ctx.has_const_decorated = TRUE ;
		}
		else if( token_info->token_type == TOKEN_TYPE_ATOMIC )
		{
			interp_stat_ctx.has_atomic_decorated = TRUE ;
		}
		else if( token_info->token_type == TOKEN_TYPE_SYNC )
		{
			interp_stat_ctx.has_sync_decorated = TRUE ;
		}
		else if( token_info->token_type == TOKEN_TYPE_FUNCTION )
		{
			nret = SyntaxAnalysisScan_func( rt , obj_name , & func ) ;
			if( nret )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SyntaxAnalysisScan_func failed[%d]" , nret )
				return GET_RUNTIME_ERROR_NO(rt);
			}
			
			if( func->func_begin_token_datapage_header == NULL )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "unexpect interf function in object defination" )
				FreeFunction( func );
				return GET_RUNTIME_ERROR_NO(rt);
			}
			
			SetFunctionAccessQuelifier( func , interp_stat_ctx.has_access_qualifier );
			
			if( interp_stat_ctx.has_sync_decorated == TRUE )
			{
				SetSynchronizeFunction( func );
			}
			
			nret = AddFunctionToObjectFunctionsEntity( rt , obj , func ) ;
			if( nret )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "add function entity failed[%d]" , nret )
				FreeFunction( func );
				return GET_RUNTIME_ERROR_NO(rt);
			}
			
			if( GetFunctionOutParameter(func) == NULL )
			{
				char	*p_func_name = GetFunctionName(func) ;
				
				if( p_func_name[0] == '~' && STRCMP( p_func_name+1 , == , obj_name ) && list_empty(&(func->in_params)) )
				{
					if( TravelFunctionInputParameter( rt , func , NULL ) != NULL )
					{
						SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "declare destractor input parameters must be empty" )
						FreeFunction( func );
						return GET_RUNTIME_ERROR_NO(rt);
					}
					
					GetObjectFunctionsEntity(obj)->destractor_cache = func ;
				}
				else if( STRCMP( p_func_name , == , obj_name ) && list_empty(&(func->in_params)) )
				{
					GetObjectFunctionsEntity(obj)->constractor_cache = func ;
				}
			}
			
			memset( & interp_stat_ctx , 0x00 , sizeof(struct ZlangInterpretStatementContext) );
			memset( & interp_expr_ctx , 0x00 , sizeof(struct ZlangInterpretExpressionContext) );
		}
		else if( token_info->token_type == TOKEN_TYPE_INTERCEPT )
		{
			nret = SyntaxAnalysisScan_object_intercept( rt , & intercept ) ;
			if( nret )
				return GET_RUNTIME_ERROR_NO(rt);
			
			prop = QueryPropertyInObjectByPropertyName( rt , obj , intercept->func->func_name ) ;
			if( prop == NULL )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "query property '%s' failed[%d]" , intercept->func->func_name , nret )
				DestroyIntercept( rt , intercept );
				return ZLANG_ERROR_SYNTAX;
			}
			
			if( intercept->opportunity == ZLANG_INTERCEPT_SET )
			{
				prop->intercept_set = intercept ;
			}
			else if( intercept->opportunity == ZLANG_INTERCEPT_GET )
			{
				prop->intercept_get = intercept ;
			}
			else
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_INTERNAL , "unexpection internal error" )
				DestroyIntercept( rt , intercept );
				return ZLANG_ERROR_INTERNAL;
			}
			
			intercept->obj_name = ZLSTRDUP( GetObjectName(obj) ) ;
			if( intercept->obj_name == NULL )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc intercept's object name failed" )
				DestroyIntercept( rt , intercept );
				return ZLANG_ERROR_ALLOC;
			}
			
			list_add_tail( & (intercept->this_intercept) , & (rt->object_prop_intercepts) );
		}
		else if( token_info->token_type == TOKEN_TYPE_IDENTIFICATION )
		{
			parent_obj = QueryGlobalObjectByObjectName( rt , token ) ;
			if( parent_obj == NULL )
			{
				parent_obj = QueryPropertyInObjectByPropertyName( rt , obj , token ) ;
				if( parent_obj == NULL )
				{
					SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "query object '%s' failed" , token )
					return ZLANG_ERROR_SYNTAX;
				}
			}
			
			rt->in_obj = obj ;
			nret = InterpretExpression_DeclareObjects( rt , & interp_stat_seg_ctx , & interp_stat_ctx , & interp_expr_ctx , obj , parent_obj , NULL ) ;
			rt->in_obj = NULL ;
			if( nret != ZLANG_INFO_END_OF_EXPRESSION )
			{
				SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "InterpretExpression_DeclareObjects failed[%d]" , nret )
				return ZLANG_ERROR_SYNTAX;
			}
			NEXTTOKEN( rt )
			
			memset( & interp_stat_ctx , 0x00 , sizeof(struct ZlangInterpretStatementContext) );
			memset( & interp_expr_ctx , 0x00 , sizeof(struct ZlangInterpretExpressionContext) );
		}
		else if( token_info->token_type == TOKEN_TYPE_END_OF_STATEMENT_SEGMENT )
		{
			break;
		}
		else
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect '}' but '%s'" , token )
			return ZLANG_ERROR_SYNTAX;
		}
	}
	
	nret = SetCloneObjectName( rt , obj , obj_name ) ;
	if( nret )
		return GET_RUNTIME_ERROR_NO(rt);
	
	if( inherit_info->token_type == TOKEN_TYPE_IMPLEMENTS )
	{
		struct ZlangFunctionsEntity	*funcs_enti = GetObjectAncestorFunctionsEntity(obj) ;
		
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CheckUnimplementFunctionInObject funcs_enti[%p][%s][%d] ..." , funcs_enti,GetCloneObjectName(obj),GetFunctionsEntityReferCount(funcs_enti) )
		nret = CheckUnimplementFunctionInObject( rt , obj , funcs_enti ) ;
		TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CheckUnimplementFunctionInObject funcs_enti[%p][%s][%d] return[%d]" , funcs_enti,GetCloneObjectName(obj),GetFunctionsEntityReferCount(funcs_enti) , nret )
		if( nret )
		{
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	if( pp_obj )
		(*pp_obj) = obj ;
	return 0;
}

int SyntaxAnalysisScan_interf( struct ZlangRuntime *rt , struct ZlangInterface **pp_interf )
{
	struct ZlangTokenDataUnitHeader			*token_info = NULL ;
	char						*token = NULL ;
	struct ZlangInterface				*interf = NULL ;
	struct ZlangTokenDataUnitHeader			*interf_name_info = NULL ;
	char						*interf_name = NULL ;
	struct ZlangObject				*parent_obj = NULL ;
	struct ZlangFunction				*func = NULL ;
	struct ZlangInterpretStatementSegmentContext	interp_stat_seg_ctx ;
	struct ZlangInterpretStatementContext		interp_stat_ctx ;
	struct ZlangInterpretExpressionContext		interp_expr_ctx ;
	
	int						nret = 0 ;
	
	/*
		'interface' interf_name
		#1          #2
		{
		#9
			'public|private' parent_obj_name '<' ext_obj_name , ext_obj2_name '>'  obj_name ;
                        #13              #14                                                   #15
			
			'public|private' function ...
			#23              #24
		}
		#99
	*/
	
	/* #2 */
	TRAVELTOKEN_AND_SAVEINFO( rt , interf_name_info , interf_name )
	
	/* #3 */
	TRAVELTOKEN_AND_SAVEINFO( rt , token_info , token )
	if( token_info->token_type == TOKEN_TYPE_BEGIN_OF_STATEMENT_SEGMENT )
	{
		interf = CreateInterface( rt , interf_name ) ;
		if( interf == NULL )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "CreateInterface failed" )
			return nret;
		}
	}
	else
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect 'extends' or '{'" )
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	memset( & interp_stat_seg_ctx , 0x00 , sizeof(struct ZlangInterpretStatementSegmentContext) );
	memset( & interp_stat_ctx , 0x00 , sizeof(struct ZlangInterpretStatementContext) );
	memset( & interp_expr_ctx , 0x00 , sizeof(struct ZlangInterpretExpressionContext) );
	for( ; ; )
	{
		/* #13 or #23 or #99 */
		TRAVELTOKEN_AND_SAVEINFO( rt , token_info , token )
		QueryCharsetAliasAndChangeTokenInfo( rt , token_info , & token );
		if( token_info->token_type == TOKEN_TYPE_PUBLIC )
		{
			interp_stat_ctx.has_access_qualifier = ZLANG_ACCESSQUALIFIER_PUBLIC ;
		}
		else if( token_info->token_type == TOKEN_TYPE_PRIVATE )
		{
			interp_stat_ctx.has_access_qualifier = ZLANG_ACCESSQUALIFIER_PRIVATE ;
		}
		else if( token_info->token_type == TOKEN_TYPE_CONST )
		{
			interp_stat_ctx.has_const_decorated = TRUE ;
		}
		else if( token_info->token_type == TOKEN_TYPE_ATOMIC )
		{
			interp_stat_ctx.has_atomic_decorated = TRUE ;
		}
		else if( token_info->token_type == TOKEN_TYPE_FUNCTION )
		{
			nret = SyntaxAnalysisScan_func( rt , NULL , & func ) ;
			if( nret )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "SyntaxAnalysisScan_func failed[%d]" , nret )
				return GET_RUNTIME_ERROR_NO(rt);
			}
			
			SetFunctionAccessQuelifier( func , interp_stat_ctx.has_access_qualifier );
			
			nret = AddFunctionToObjectFunctionsEntity( rt , interf->inner , func ) ;
			if( nret )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "AddFunctionToObjectFunctionsEntity failed[%d]" , nret )
				FreeFunction( func );
				return nret;
			}
			
			memset( & interp_stat_seg_ctx , 0x00 , sizeof(struct ZlangInterpretStatementSegmentContext) );
			memset( & interp_stat_ctx , 0x00 , sizeof(struct ZlangInterpretStatementContext) );
			memset( & interp_expr_ctx , 0x00 , sizeof(struct ZlangInterpretExpressionContext) );
		}
		else if( token_info->token_type == TOKEN_TYPE_IDENTIFICATION )
		{
			parent_obj = QueryGlobalObjectByObjectName( rt , token ) ;
			if( parent_obj == NULL )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "QueryGlobalObjectByObjectName failed" )
				return GET_RUNTIME_ERROR_NO(rt);
			}
			
			nret = InterpretExpression_DeclareObjects( rt , & interp_stat_seg_ctx , & interp_stat_ctx , & interp_expr_ctx , interf->inner , parent_obj , NULL ) ;
			if( nret != ZLANG_INFO_END_OF_EXPRESSION )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InterpretExpression_DeclareObjects failed[%d]" , nret )
				return GET_RUNTIME_ERROR_NO(rt);
			}
			NEXTTOKEN( rt )
			
			memset( & interp_stat_seg_ctx , 0x00 , sizeof(struct ZlangInterpretStatementSegmentContext) );
			memset( & interp_stat_ctx , 0x00 , sizeof(struct ZlangInterpretStatementContext) );
			memset( & interp_expr_ctx , 0x00 , sizeof(struct ZlangInterpretExpressionContext) );
		}
		else if( token_info->token_type == TOKEN_TYPE_END_OF_STATEMENT_SEGMENT )
		{
			break;
		}
		else
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect '}' but '%s'" , token )
			return ZLANG_ERROR_SYNTAX;
		}
	}
	
	interf->interf_name = GetObjectName(GetInterfaceInner(interf)) ;
	
	nret = SetCloneObjectName( rt , GetInterfaceInner(interf) , interf_name ) ;
	if( nret )
		return GET_RUNTIME_ERROR_NO(rt);
	
	if( pp_interf )
		(*pp_interf) = interf ;
	return 0;
}

int SyntaxAnalysisScan_intercept( struct ZlangRuntime *rt , struct ZlangIntercept **pp_intercept )
{
	struct ZlangTokenDataUnitHeader		*token_info = NULL ;
	char					*token = NULL ;
	struct ZlangIntercept			*intercept = NULL ;
	unsigned char				opportunity ;
	struct ZlangTokenDataUnitHeader		*obj_and_func_name_info = NULL ;
	char					*obj_and_func_name = NULL ;
	struct ZlangFunction			*func = NULL ;
	struct ZlangFunctionParameter		*func_in_param = NULL ;
	struct ZlangTokenDataUnitHeader		*param_obj_name_info = NULL ;
	char					*param_obj_name = NULL ;
	struct ZlangTokenDataUnitHeader		*param_func_name_info = NULL ;
	char					*param_func_name = NULL ;
	struct ZlangTokenDataUnitHeader		*param_in_array_name_info = NULL ;
	char					*param_in_array_name = NULL ;
	struct ZlangTokenDataUnitHeader		*param_out_array_name_info = NULL ;
	char					*param_out_array_name = NULL ;
	struct ZlangTokenDataUnitHeader		*begin_of_statment_segment_token_info = NULL ;
	char					*full_func_name = NULL ;
	int					nret = 0 ;
	
	func = CreateFunction( rt , NULL , NULL , NULL ) ;
	if( func == NULL )
		return GET_RUNTIME_ERROR_NO(rt);
	
	/*
		"intercept" "before|after" object.func|func "(" "object" obj_name , "funcp" func_name , "array" in_array_name , "array" out_array_name ")" "{" ... "}"
                            #2             #3               #4  #5       #6       #7        #9        #10                       #14     #15             #16
                                                                                    #8                  #11     #12           #13                           #17     #18
	*/
	
	/* #2 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type == TOKEN_TYPE_BEFORE )
	{
		opportunity = ZLANG_INTERCEPT_BEFORE ;
	}
	else if( token_info->token_type == TOKEN_TYPE_AFTER )
	{
		opportunity = ZLANG_INTERCEPT_AFTER ;
	}
	else
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect 'before' or 'after' after 'intercept' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #3 */
	TRAVELTOKEN( rt , obj_and_func_name_info , obj_and_func_name )
	if( obj_and_func_name_info->token_type != TOKEN_TYPE_IDENTIFICATION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect 'object.func' after intercept opportunity , but '%s'" , obj_and_func_name )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	nret = SetFunctionName( rt , func , obj_and_func_name ) ;
	if( nret )
	{
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #4 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_BEGIN_OF_SUB_EXPRESSION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect '(' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #5 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_OBJECT )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect 'object' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #6 */
	TRAVELTOKEN( rt , param_obj_name_info , param_obj_name )
	if( param_obj_name_info->token_type != TOKEN_TYPE_IDENTIFICATION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect TOKEN_TYPE_IDENTIFICATION , but '%s'" , param_obj_name )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	func_in_param = AddFunctionInputParameterInFunction( rt , func , ZLANG_OBJECT_object , param_obj_name ) ;
	if( func_in_param == NULL )
	{
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #7 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_PART_OF_STATEMENT )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect ',' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #8 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_IDENTIFICATION || STRCMP( token , != , ZLANG_OBJECT_functionptr ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect 'functionptr' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #9 */
	TRAVELTOKEN( rt , param_func_name_info , param_func_name )
	if( param_func_name_info->token_type != TOKEN_TYPE_IDENTIFICATION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect TOKEN_TYPE_IDENTIFICATION , but '%s'" , param_func_name )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	func_in_param = AddFunctionInputParameterInFunction( rt , func , ZLANG_OBJECT_functionptr , param_func_name ) ;
	if( func_in_param == NULL )
	{
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #10 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_PART_OF_STATEMENT )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect ',' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #11 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_IDENTIFICATION || STRCMP( token , != , ZLANG_OBJECT_array ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect 'array' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #12 */
	TRAVELTOKEN( rt , param_in_array_name_info , param_in_array_name )
	if( param_in_array_name_info->token_type != TOKEN_TYPE_IDENTIFICATION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect TOKEN_TYPE_IDENTIFICATION , but '%s'" , param_in_array_name )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	func_in_param = AddFunctionInputParameterInFunction( rt , func , ZLANG_OBJECT_array , param_in_array_name ) ;
	if( func_in_param == NULL )
	{
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #13 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_PART_OF_STATEMENT )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect ',' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #14 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_IDENTIFICATION || STRCMP( token , != , ZLANG_OBJECT_array ) )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect 'array' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #15 */
	TRAVELTOKEN( rt , param_out_array_name_info , param_out_array_name )
	if( param_out_array_name_info->token_type != TOKEN_TYPE_IDENTIFICATION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect TOKEN_TYPE_IDENTIFICATION , but '%s'" , param_out_array_name )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	func_in_param = AddFunctionInputParameterInFunction( rt , func , ZLANG_OBJECT_array , param_out_array_name ) ;
	if( func_in_param == NULL )
	{
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #16 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_END_OF_SUB_EXPRESSION )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect ')' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	/* #17 */
	TRAVELTOKEN( rt , token_info , token )
	if( token_info->token_type != TOKEN_TYPE_BEGIN_OF_STATEMENT_SEGMENT )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "expect '{' , but '%s'" , token )
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	begin_of_statment_segment_token_info = token_info ;
	
	func->func_begin_token_datapage_header = rt->travel_token_datapage_header ;
	func->func_begin_token_dataunit = rt->travel_token_dataunit ;
	
	/* #18,#19 */
	nret = SyntaxAnalysisScan_func_body( rt , begin_of_statment_segment_token_info , NULL , & token_info , & token , 1 , TOKEN_TYPE_END_OF_STATEMENT_SEGMENT ) ;
	if( nret )
	{
		FreeFunction( func );
		return nret;
	}
	
	func->func_end_over_token_datapage_header = rt->travel_token_datapage_header ;
	func->func_end_over_token_dataunit = rt->travel_token_dataunit ;
	
	full_func_name = GenerateFullFunctionName( rt , func , & (func->in_params) , func->out_param ) ;
	if( full_func_name == NULL )
	{
		FreeFunction( func );
		return GET_RUNTIME_ERROR_NO(rt);
	}
	
	LinkFullFunctionName( func , full_func_name );
	
	/* create intercept */
	intercept = CreateIntercept( rt , opportunity , obj_and_func_name , func ) ;
	if( intercept == NULL )
	{
		FreeFunction( func );
		return nret;
	}
	
	if( pp_intercept )
		(*pp_intercept) = intercept ;
	else
		DestroyIntercept( rt , intercept );
	return 0;
}

int SyntaxAnalysisScan( struct ZlangRuntime *rt )
{
	struct ZlangTokenDataUnitHeader		*token_info = NULL ;
	char					*token = NULL ;
	struct ZlangInterpretStatementContext	interp_stat_ctx ;
	struct ZlangFunction			*func = NULL ;
	struct ZlangObject			*obj = NULL ;
	struct ZlangIntercept			*intercept = NULL ;
	struct ZlangInterface			*interf = NULL ;
	
	int					nret = 0 ;
	
	memset( & interp_stat_ctx , 0x00 , sizeof(struct ZlangInterpretStatementContext) );
	
	rt->travel_token_datapage_header = list_first_entry( & (rt->token_datapage_list) , struct ZlangTokenDataPageHeader , this_token_datapage ) ;
	rt->travel_token_dataunit = NULL ;
	for( ; ; )
	{
		TRAVELTOKEN_AND_SAVEINFO( rt , token_info , token , if(nret==ZLANG_INFO_TRAVEL_TOKEN_OUT){break;}else ) 
		if( token_info->token_type == TOKEN_TYPE_IMPORT )
		{
			nret = Keyword_import( rt ) ;
			if( nret )
				return nret;
		}
		else if( token_info->token_type == TOKEN_TYPE_SYNC )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TOKEN_TYPE_SYNC" )
			interp_stat_ctx.has_sync_decorated = TRUE ;
		}
		else if( token_info->token_type == TOKEN_TYPE_FUNCTION )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TOKEN_TYPE_FUNCTION" )
			
			nret = SyntaxAnalysisScan_func( rt , NULL , & func ) ;
			if( nret )
				return GET_RUNTIME_ERROR_NO(rt);
			
			if( interp_stat_ctx.has_sync_decorated == TRUE )
			{
				SetSynchronizeFunction( func );
			}
			
			LinkFunctionToRuntimeFunctionsTreeByFunctionName( rt , func );
			LinkFunctionToRuntimeFunctionsTreeByFullFunctionName( rt , func );
			
			memset( & interp_stat_ctx , 0x00 , sizeof(struct ZlangInterpretStatementContext) );
		}
		else if( token_info->token_type == TOKEN_TYPE_OBJECT )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TOKEN_TYPE_OBJECT" )
			
			nret = SyntaxAnalysisScan_object( rt , & obj ) ;
			if( nret )
				return GET_RUNTIME_ERROR_NO(rt);
			
			nret = ImportObjectToGlobalObjectsHeap( rt , obj , NULL ) ;
			if( nret )
				return GET_RUNTIME_ERROR_NO(rt);
		}
		else if( token_info->token_type == TOKEN_TYPE_INTERFACE )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TOKEN_TYPE_INTERFACE" )
			
			nret = SyntaxAnalysisScan_interf( rt , & interf ) ;
			if( nret )
				return GET_RUNTIME_ERROR_NO(rt);
			
			LinkInterfaceToRuntimeInterfacesHeapByInterfaceName( rt , interf );
		}
		else if( token_info->token_type == TOKEN_TYPE_INTERCEPT )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "TOKEN_TYPE_INTERCEPT" )
			
			nret = SyntaxAnalysisScan_intercept( rt , & intercept ) ;
			if( nret )
				return GET_RUNTIME_ERROR_NO(rt);
			
			list_add_tail( & (intercept->this_intercept) , & (rt->global_intercepts) );
		}
		else
		{
			SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_SYNTAX , "unexpect '%s'" , token )
			return GET_RUNTIME_ERROR_NO(rt);
		}
	}
	
	return 0;
}

